Skip to content

Comments

feat(x2a): Track and display commit ID per job#2364

Merged
eloycoto merged 5 commits intoredhat-developer:mainfrom
elai-shalev:commit-id-tracking
Feb 23, 2026
Merged

feat(x2a): Track and display commit ID per job#2364
eloycoto merged 5 commits intoredhat-developer:mainfrom
elai-shalev:commit-id-tracking

Conversation

@elai-shalev
Copy link
Contributor

@elai-shalev elai-shalev commented Feb 19, 2026

User description

This PR will introduce tracking and displaying of cimmit id per job, to keep track for the "latest commit on the target repository created by the x2a job"

UPDATE: tested after commitID reporting was merged on x2a-converter, and is working great

  • Each K8s job (analyze, migrate, publish) pushes to the target repo. This PR captures the git commit SHA produced by each job and displays it on the Module
    page so users can trace exactly which commit a phase produced.
  • Adds commit_id column to the jobs table, extends the OpenAPI spec and collectArtifacts endpoint to accept commitId, and updates the job shell script to
    capture the SHA via git rev-parse HEAD after a successful push.
  • The frontend Module page now shows a "Last Commit ID" field per phase tab.

JIRA: https://issues.redhat.com/browse/FLPATH-3297

image

PR Type

Enhancement


Description

  • Add commit_id column to jobs table for tracking git commits

  • Extend OpenAPI spec and collectArtifacts endpoint to accept commitId

  • Update job shell script to capture SHA via git rev-parse HEAD

  • Display "Last Commit ID" field on Module page per phase tab

  • Add internationalization support for commit ID label (DE, ES, FR, IT)


Diagram Walkthrough

flowchart LR
  A["Job Execution"] -->|"git push"| B["Capture Commit SHA"]
  B -->|"git rev-parse HEAD"| C["Store in COMMIT_ID"]
  C -->|"report_result"| D["collectArtifacts Endpoint"]
  D -->|"commitId parameter"| E["Update Job Record"]
  E -->|"commit_id column"| F["Database"]
  F -->|"Job model"| G["Module Page Display"]
  G -->|"Last Commit ID field"| H["User Interface"]
Loading

File Walkthrough

Relevant files
Database schema
1 files
2025012401_create_jobs_table.ts
Add commit_id column to jobs table                                             
+1/-0     
Api enhancement
1 files
collectArtifacts.ts
Extend collectArtifacts endpoint with commitId parameter 
+3/-0     
Model definition
4 files
Job.model.ts
Add commitId field to Job model interface                               
+4/-0     
ProjectsProjectIdCollectArtifactsPostRequest.model.ts
Add commitId to collectArtifacts request model                     
+4/-0     
Job.model.ts
Add commitId field to client-side Job model                           
+4/-0     
ProjectsProjectIdCollectArtifactsPostRequest.model.ts
Add commitId to client-side request model                               
+4/-0     
Api specification
2 files
router.ts
Update OpenAPI spec with commitId field definitions           
+8/-0     
openapi.yaml
Define commitId in OpenAPI specification                                 
+6/-0     
Service enhancement
1 files
index.ts
Add commitId parameter to updateJob method signature         
+1/-0     
Database operations
1 files
jobOperations.ts
Include commit_id in job queries and update operations     
+7/-0     
Data mapping
1 files
mappers.ts
Map commit_id database field to commitId model property   
+1/-0     
Internationalization
5 files
de.ts
Add German translation for Last Commit ID label                   
+1/-0     
es.ts
Add Spanish translation for Last Commit ID label                 
+1/-0     
fr.ts
Add French translation for Last Commit ID label                   
+1/-0     
it.ts
Add Italian translation for Last Commit ID label                 
+1/-0     
ref.ts
Add English reference translation for commit ID                   
+1/-0     
Shell script enhancement
1 files
x2a-job-script.sh
Capture and report commit SHA after successful push           
+7/-0     
Documentation
2 files
report.api.md
Document commitId in public API report                                     
+2/-0     
report.api.md
Document commitId translation key in API report                   
+1/-0     
Ui enhancement
1 files
PhasesCard.tsx
Display Last Commit ID field on Module page                           
+6/-0     

@elai-shalev elai-shalev marked this pull request as draft February 19, 2026 14:22
@rhdh-gh-app
Copy link

rhdh-gh-app bot commented Feb 19, 2026

Missing Changesets

The following package(s) are changed by this PR but do not have a changeset:

  • @red-hat-developer-hub/backstage-plugin-x2a-backend
  • @red-hat-developer-hub/backstage-plugin-x2a-common
  • @red-hat-developer-hub/backstage-plugin-x2a

See CONTRIBUTING.md for more information about how to add changesets.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-x2a-backend workspaces/x2a/plugins/x2a-backend none v1.0.1
@red-hat-developer-hub/backstage-plugin-x2a-common workspaces/x2a/plugins/x2a-common none v1.0.1
@red-hat-developer-hub/backstage-plugin-x2a workspaces/x2a/plugins/x2a none v1.0.1

@rhdh-qodo-merge
Copy link

rhdh-qodo-merge bot commented Feb 19, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Unvalidated input storage

Description: commitId is accepted as an arbitrary optional string and persisted to the jobs.commit_id
column without format/length validation, which could enable stored untrusted data issues
(e.g., excessively large payloads for DB/log bloat, or injection/XSS risks if any
downstream consumer renders commitId without escaping/sanitization); consider constraining
it to a Git SHA pattern (e.g., ^[0-9a-f]{7,40}$) and enforcing a sane max length at both
API and DB levels.
collectArtifacts.ts [58-170]

Referred Code
const collectArtifactsRequestSchema = z.object({
  status: z.enum(['success', 'error']),
  errorDetails: z.string().optional(),
  jobId: z.string().uuid('Job ID must be a valid UUID'),
  artifacts: z.array(artifactSchema).optional(),
  telemetry: telemetrySchema.optional(),
  commitId: z.string().optional(),
});

export interface CollectArtifactsRequestBody {
  status: 'success' | 'error';
  errorDetails?: string;
  jobId: string;
  artifacts?: Artifact[];
  telemetry?: Telemetry;
  commitId?: string;
}

export function registerCollectArtifactsRoutes(
  router: express.Router,
  deps: RouterDeps,


 ... (clipped 92 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
No custom compliance provided

Follow the guide to enable custom compliance check.

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@rhdh-qodo-merge
Copy link

rhdh-qodo-merge bot commented Feb 19, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Capture commit ID before pushing

In x2a-job-script.sh, capture the git commit hash before the git push command
and clear it if the push fails to ensure the correct commit ID is always used.

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh [95-100]

+COMMIT_ID=$(git rev-parse HEAD 2>/dev/null || echo "")
 if ! git push origin "${TARGET_REPO_BRANCH}"; then
   PUSH_FAILED="Failed to push to ${TARGET_REPO_URL} branch ${TARGET_REPO_BRANCH}"
   echo "ERROR: ${PUSH_FAILED}"
-else
-  COMMIT_ID=$(git rev-parse HEAD 2>/dev/null || echo "")
+  COMMIT_ID=""
 fi
  • Apply / Chat
Suggestion importance[1-10]: 3

__

Why: The suggestion correctly identifies a potential for improvement in the script's logic, although the race condition described is unlikely. The proposed change to capture the COMMIT_ID before the push and clear it on failure is a slightly cleaner and more robust pattern.

Low
  • Update

@rhdh-qodo-merge
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Unvalidated stored input

Description: The new commitId field is accepted from the request and persisted to the database
(updateJob with commitId) without format/length validation, which could enable stored
payloads (e.g., very long strings for DB/log pollution or, if rendered unsafely elsewhere,
stored XSS) to propagate to downstream consumers and the UI.
collectArtifacts.ts [58-170]

Referred Code
const collectArtifactsRequestSchema = z.object({
  status: z.enum(['success', 'error']),
  errorDetails: z.string().optional(),
  jobId: z.string().uuid('Job ID must be a valid UUID'),
  artifacts: z.array(artifactSchema).optional(),
  telemetry: telemetrySchema.optional(),
  commitId: z.string().optional(),
});

export interface CollectArtifactsRequestBody {
  status: 'success' | 'error';
  errorDetails?: string;
  jobId: string;
  artifacts?: Artifact[];
  telemetry?: Telemetry;
  commitId?: string;
}

export function registerCollectArtifactsRoutes(
  router: express.Router,
  deps: RouterDeps,


 ... (clipped 92 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
🟢
No codebase code duplication found No new components were introduced in the PR code
Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Missing input validation: The new external input commitId is accepted as an unconstrained string and persisted
without validating it as a git SHA (e.g., hex format and length) or enforcing a reasonable
max length.

Referred Code
const collectArtifactsRequestSchema = z.object({
  status: z.enum(['success', 'error']),
  errorDetails: z.string().optional(),
  jobId: z.string().uuid('Job ID must be a valid UUID'),
  artifacts: z.array(artifactSchema).optional(),
  telemetry: telemetrySchema.optional(),
  commitId: z.string().optional(),
});

export interface CollectArtifactsRequestBody {
  status: 'success' | 'error';
  errorDetails?: string;
  jobId: string;
  artifacts?: Artifact[];
  telemetry?: Telemetry;
  commitId?: string;
}

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@rhdh-qodo-merge
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Avoid capturing an incorrect commit ID

In the x2a-job-script.sh file, check the exit code of the git commit command to
ensure a new commit was actually created before capturing and storing the commit
ID.

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh [92-100]

 Co-Authored-By: ${GIT_AUTHOR_NAME} <${GIT_AUTHOR_EMAIL}>
-" || true
+"
+if [ $? -eq 0 ]; then
+    # A new commit was created. Pull latest changes, push, and record the commit ID.
     git pull --rebase origin "${TARGET_REPO_BRANCH}" 2>/dev/null || true
     if ! git push origin "${TARGET_REPO_BRANCH}"; then
       PUSH_FAILED="Failed to push to ${TARGET_REPO_URL} branch ${TARGET_REPO_BRANCH}"
       echo "ERROR: ${PUSH_FAILED}"
     else
       COMMIT_ID=$(git rev-parse HEAD 2>/dev/null || echo "")
     fi
+else
+    echo "No changes to commit."
+fi

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a bug where an incorrect commit ID could be captured if no new git commit is created, and provides a robust fix.

Medium
General
Validate commit ID format

In the collectArtifactsRequestSchema, add a regex to the commitId field to
validate that it is a 40-character hexadecimal Git SHA.

workspaces/x2a/plugins/x2a-backend/src/router/collectArtifacts.ts [64]

-commitId: z.string().optional(),
+commitId: z.string().regex(/^[0-9a-f]{40}$/i, 'Commit ID must be a 40-character hex SHA').optional(),
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion improves input validation by adding a regex to ensure the commitId is a valid SHA-1 hash, enhancing data integrity.

Low
  • More

PUSH_FAILED="Failed to push to ${TARGET_REPO_URL} branch ${TARGET_REPO_BRANCH}"
echo "ERROR: ${PUSH_FAILED}"
else
COMMIT_ID=$(git rev-parse HEAD 2>/dev/null || echo "")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This else is not really needed, no? You don't need to push to get the commit id, can be before pushing it, after:

git pull --rebase origin "${TARGET_REPO_BRANCH}" 2>/dev/null || true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you don't push it to the remote, the commitID won't mean anything to the user

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I'll remove it

'Il modulo è già stato pubblicato. Riavvia la pubblicazione per aggiornare il repository di destinazione.',
'modulePage.phases.rerunPublish':
'Ripubblica nel repository di destinazione',
'modulePage.phases.commitId': 'Ultimo ID commit',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'modulePage.phases.commitId': 'Ultimo ID commit',
'modulePage.phases.commitId': 'Último ID commit',

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol, send a patch to the automatic translator 🤣

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait, this is Italian... not sure about that

@eloycoto eloycoto merged commit a9c790d into redhat-developer:main Feb 23, 2026
6 checks passed
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants